﻿using Basic.HrGatewayModular.Interface;
using Basic.HrGatewayModular.Model.Login;
using WeDonekRpc.CacheClient.Interface;
using WeDonekRpc.Helper;

namespace Basic.HrGatewayModular.ExtendService
{
    internal class LoginVerService : ILoginVerService
    {
        private readonly ILoginVerConfig _Config;
        private readonly ICacheController _Cache;
        private const string _CacheKey = "LoginVerState_";
        public LoginVerService ( ICacheController cache, ILoginVerConfig config )
        {
            this._Config = config;
            this._Cache = cache;
        }

        public bool CheckVerState ( string loginName )
        {
            if ( this._Config.IsOpenVer )
            {
                string key = _CacheKey + loginName;
                if ( this._Cache.TryGet(key, out LoginVerState state) == false )
                {
                    return true;
                }
                else if ( state.IsLock )
                {
                    throw new ErrorException("hr.user.already.lock", Tools.FormatTime((int)( state.LockTime.Value - DateTime.Now ).TotalSeconds));
                }
                else
                {
                    return state.ErrorNum < this._Config.VerCodeErrorNum;
                }
            }
            return true;
        }
        public bool CheckIsVer ( ErrorException e )
        {
            return this._Config.IsOpenVer && this._Config.LoginFailCode.Contains(e.ErrorCode);
        }
        public bool LoginFail ( string loginName )
        {
            string key = _CacheKey + loginName;
            if ( !this._Cache.TryGet(key, out LoginVerState state) )
            {
                state = new LoginVerState()
                {
                    ErrorNum = 0,
                    IsLock = false
                };
            }
            state.ErrorNum += 1;
            if ( state.ErrorNum >= this._Config.LockErrorNum )
            {
                state.IsLock = true;
                state.LockTime = DateTime.Now.AddSeconds(this._Config.LockTime);
                _ = this._Cache.Set(key, state, state.LockTime.Value);
            }
            else
            {
                _ = this._Cache.Set(key, state, DateTime.Now.AddSeconds(this._Config.StatisticWindow));
            }
            return state.ErrorNum >= this._Config.VerCodeErrorNum;
        }

        public bool CheckIsVerCode ( string loginName )
        {
            if ( !this._Config.IsOpenVer )
            {
                return false;
            }
            string key = string.Concat(_CacheKey, loginName);
            if ( !this._Cache.TryGet(key, out LoginVerState state) )
            {
                return false;
            }
            return state.ErrorNum >= this._Config.VerCodeErrorNum;
        }

        public void Clear ( string loginName )
        {
            if ( this._Config.IsOpenVer )
            {
                string key = string.Concat(_CacheKey, loginName);
                _ = this._Cache.Remove(key);
            }
        }
    }
}
